﻿/* Copyright (C) 2013 GruntXProductions
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */


using System;
using System.Collections.Generic;
using System.Text;
using Sys = Cosmos.System;

namespace GDOS
{
    public class Kernel : Sys.Kernel
    {
        public static string CurrentDirectory = "A:\\";
        public static VirtualFileSystem FileSystem;
        private static List<Command> commands = new List<Command>();
        private bool Echo = true;
        public static void Panic(string err)
        {
            Console.BackgroundColor = ConsoleColor.DarkBlue;
            Console.ForegroundColor = ConsoleColor.White;
            Console.Clear();
            // The cosmos console class sucks, I should have rewritten it like in Grunty OS
            // but using a different class for output would create confusion so I decieded
            // not too
            for (int i = 0; i < (80 * 26); i++)
                Console.Write(" ");
            Console.CursorLeft = 0;
            Console.CursorTop = 0;
            Console.WriteLine("A problem has been detected and GDOS has been shutdown to prevent damage to yourcomputer.\n");

            Console.WriteLine(err);
            Console.WriteLine(@"
If this is the first time you've seen this Stop error screen, 
restart you computer. If this screen appears again follow
these steps:

Check to make sure any new hardware or software is properlt installed.
If this is a new installation, check your hardware to see if it is 
compatible with GDOS

If problems continue, disable or remove any newly installed hardware
or software. Disable BIOS memory options such as caching or shadowing.");
            while (true) ;
        }
        protected override void BeforeRun()
        {
            Console.WriteLine("Starting G-DOS...");
            // Lets add all of the commands we want to use to the list
            commands.Add(new Commands.Dir());
            commands.Add(new Commands.Fdisk());
            commands.Add(new Commands.Format());
            commands.Add(new Commands.Format());
            commands.Add(new Commands.CD());
            commands.Add(new Commands.Mkdir());
            commands.Add(new Commands.Del());
            commands.Add(new Commands.cls());
           // Interrupts.setIDTGate(0x80, API.HandleInt0x80); // Set up the assembly API
            bool usableDriveFound = false; // if no GLNFS partition is detected then we need to do something
            while (!usableDriveFound)
            {
                GruntyOS.HAL.ATA.Detect(); // This will detect all ATA devices and add them to the device filesystem
                FileSystem = new VirtualFileSystem(); // We need to make sure VirtualFileSystem is not null
                GruntyOS.CurrentUser.Privilages = 0; // This has to be set, 1 = limited 0 = root
                GruntyOS.CurrentUser.Username = "DOS"; // When using anything under the filenamespace this will be the defualt username
               
                GruntyOS.HAL.FileSystem.Root = new GruntyOS.HAL.RootFilesystem();
                GruntyOS.HAL.FileSystem.Root.Seperator = '\\'; // Use \ instead of /
                for (int i = 0; i < GruntyOS.HAL.Devices.dev.Count; i++)
                {
                    if (GruntyOS.HAL.Devices.dev[i].dev is Cosmos.Hardware.BlockDevice.Partition)
                    {
                        GruntyOS.HAL.GLNFS FS = new GruntyOS.HAL.GLNFS((Cosmos.Hardware.BlockDevice.Partition)GruntyOS.HAL.Devices.dev[i].dev);

                        usableDriveFound = true;
                        if (GruntyOS.HAL.GLNFS.isGFS((Cosmos.Hardware.BlockDevice.Partition)GruntyOS.HAL.Devices.dev[i].dev))
                        {
                            Console.WriteLine("Drive detected!");
                        }
                        Drive drive = new Drive();
                        drive.Filesystem = FS;
                        drive.DeviceFile = GruntyOS.HAL.Devices.dev[i].name;
                        FileSystem.AddDrive(drive);
                    }
                }
                if (!usableDriveFound)
                {
                    Execute("fdisk");
                    Console.WriteLine("Please reboot (and do not forget to format the partition you detected!)");
                    while (true) ;

                }
            }
         
            GruntyOS.HAL.FileSystem.Root.Mount("\\", FileSystem); // mount the virtual filesystem (We are actually mounting the virtual filesystem onto another virtual filesystem, Grunty OSes default virtual filesystem)

        }
        
        protected override void Run()
        {
            
            while (true)
            {
                if(Echo)
                    Console.Write(CurrentDirectory + "> ");
                string cmd = Console.ReadLine();
                Execute(cmd);
           
                
            }
        }
        public static void Execute(string cmd)
        {
         
            Scanner scanner = new Scanner();
            List<object> args = scanner.getTokens(cmd);
            List<string> argsString = new List<string>();
            bool executed = false;
            for (int i = 0; i < args.Count; i++)
            {
                if (args[i] is Scanner.StringLiteral)
                    argsString.Add(((Scanner.StringLiteral)args[i]).Value);
                else
                    argsString.Add(args[i].ToString());
            }
            for (int i = 0; i < commands.Count; i++)
            {
                if (commands[i].Name == argsString[0])
                {
                    commands[i].Execute(argsString.ToArray());
                    executed = true;
                    break;
                }
            }
            if (!executed) // Hmm no command found. The command must be an external progam then
            {
                try
                {
                    EXE.PE32 prog = new EXE.PE32(GruntyOS.String.Util.cleanName(CurrentDirectory) + @"\" + args[0]);
                    //com32.Execute(); // run the program
                }
                catch
                {
                    Console.WriteLine("Not an internal command or external file!");
                }
            }
        }

    }
}
